package com.example.springbott.wx_controller;

import com.example.springbott.bean.BaseRespVo;
import com.example.springbott.bean.MarketUser;
import com.example.springbott.bean.silic.AuthReCatchaBo;
import com.example.springbott.bean.silic.WXAuthRegisterBo;
import com.example.springbott.config.MarketToken;
import com.example.springbott.util.Count;
import com.example.springbott.util.WXAuthLoginUtil;
import com.example.springbott.util.WXAuthReCaptchaUtil;
import com.example.springbott.util.regexUtil.RegexUtils;
import com.example.springbott.wx_bean_heheer.Dateinfo;
import com.example.springbott.wx_bean_heheer.LoginBO;
import com.example.springbott.wx_bean_heheer.UserInfo;

import com.example.springbott.wx_service.WXAuthService;
import lombok.SneakyThrows;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

/**
 * @author 1784549954@qq.com
 * @since 2022/11/22 14:13
 */
@RestController
@RequestMapping("wx/auth")
public class WXAuthController {

    @Autowired
    WXAuthService wxAuthService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @RequestMapping("login")
    public BaseRespVo AuthLogin(@RequestBody LoginBO loginBO){
        String username = loginBO.getUsername();
        String password = loginBO.getPassword();
        Subject subject = SecurityUtils.getSubject();
        MarketToken marketToken = new MarketToken(username, password, Count.TYPE_WX);
        Dateinfo dateinfo = new Dateinfo();
        UserInfo userInfo = new UserInfo();
        try {
            subject.login(marketToken);
        } catch (AuthenticationException e) {

            e.printStackTrace();

            return BaseRespVo.unAuthc();
        }
        if (subject.isAuthenticated()){
            MarketUser principal = (MarketUser) subject.getPrincipals().getPrimaryPrincipal();
            dateinfo.setToken(subject.getSession().getId().toString());
            userInfo.setNickName(principal.getNickname());
            userInfo.setAvatarUrl(principal.getAvatar());
            dateinfo.setUserInfo(userInfo);
            return BaseRespVo.ok(dateinfo);

        }


        return BaseRespVo.ok(dateinfo);
    }


    @RequestMapping("logout")
    public BaseRespVo AuthLogout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return BaseRespVo.ok(null);
    }


    /**
     *  注册--短信验证码 reCaptcha
     *
     * @param /{mobile: "18822210222"}
     * @return {"errno":0,"errmsg":"成功"}
     * @author  silic xia
     * @since 2022/11/22 19:52
     */
    @RequestMapping("regCaptcha")
    public BaseRespVo wxAuthReCaptcha(@RequestBody AuthReCatchaBo authReCatchaBo, HttpServletResponse response){
        String smsCode = WXAuthReCaptchaUtil.getSMSReCatcha(authReCatchaBo);
        // 存储到redis，设置过期时间,key必须要加上phone确保只有这个手机号能用这个code
        stringRedisTemplate.opsForValue().set(Count.SMSCODE + authReCatchaBo.getMobile(),smsCode);
        stringRedisTemplate.expire(Count.SMSCODE + authReCatchaBo.getMobile(),5, TimeUnit.MINUTES);
        return BaseRespVo.ok();
    }


    /**
     * 注册 /register
     * 插入表中
     *
     * @param {"username":"woliale","password":"123456","mobile":"18029226881","
     * code":"073335","wxCode":"the code is a mock one"} 要验证code是否正确,检查手机号是否重复
     *
     * @return token: "eyJhbrza5IoWok"
     *          userInfo: {nickName: "woliale",…}
     *      data:{}
     *      errmsg: "成功"
     *      errno: 0
     * @author  silic xia
     * @since 2022/11/22 20:43
     */
    @SneakyThrows
    @RequestMapping("register")
    public BaseRespVo wxAuthRegister(@RequestBody WXAuthRegisterBo wxAuthRegisterBo, HttpServletResponse response){
        // 校验验证码、手机号输入合法性
        if (RegexUtils.isPasswordInvalid(wxAuthRegisterBo.getPassword())){
            return BaseRespVo.fail("密码格式不正确！密码必须由字母、数字、特殊符号组成，包含（. _ ~ ! @ # $ ^ & *），区分大小写，且密码长度为8-20位",Count.REGISTER_PASSWORD_FORMAT_ERROR);
        }
        if (RegexUtils.isPhoneInvalid(wxAuthRegisterBo.getMobile())){
            return BaseRespVo.fail("手机号格式不正确！",Count.REGISTER_PHONE_FORMAT_ERROR);
        }
        if (RegexUtils.isCodeInvalid(wxAuthRegisterBo.getCode())){
            return BaseRespVo.fail("验证码格式不正确！请输入5位数字...",Count.REGISTER_CODE_FORMAT_ERROR);
        }
        if (checkSMSCodeVaild(wxAuthRegisterBo)) return BaseRespVo.fail("短信验证码不一致！", Count.REGISTER_CODE_ERROR);


        // 加入数据库
        int code = wxAuthService.wxAuthRegister(wxAuthRegisterBo);
        if (code == Count.REGISTER_MOBILE_REPEATED){
            return BaseRespVo.fail("手机已被注册！",Count.REGISTER_MOBILE_REPEATED);
        }

        // 登录
        BaseRespVo baseRespVo = WXAuthLoginUtil.AuthLogin(wxAuthRegisterBo);
        return baseRespVo;
    }


    /**
     *  重置密码 reset
     *
     * @param {mobile: "18022255555", code: "1234", password: "123456"}
     * @return {"errno":703,"errmsg":"验证码错误"}
     * @author  silic xia
     * @since 2022/11/23 9:31
     */
    @RequestMapping("reset")
    public BaseRespVo wxAuthReset(@RequestBody WXAuthRegisterBo wxAuthRegisterBo,HttpSession session){
        // 校验验证码、手机号输入合法性
        if (RegexUtils.isPhoneInvalid(wxAuthRegisterBo.getMobile())){
            return BaseRespVo.fail("手机号格式不正确！",Count.REGISTER_PHONE_FORMAT_ERROR);
        }
        if (RegexUtils.isPhoneInvalid(wxAuthRegisterBo.getMobile())){
            return BaseRespVo.fail("Code格式不正确！",Count.REGISTER_CODE_FORMAT_ERROR);
        }
        if (checkSMSCodeVaild(wxAuthRegisterBo)) return BaseRespVo.fail("短信验证码不一致！", Count.REGISTER_CODE_ERROR);
        wxAuthService.wxAuthReset(wxAuthRegisterBo);
        return BaseRespVo.ok();
    }

    
    // 验证短信code是否正确
    private boolean checkSMSCodeVaild(@RequestBody WXAuthRegisterBo wxAuthRegisterBo) {

        String smsCode = stringRedisTemplate.opsForValue().get(Count.SMSCODE + wxAuthRegisterBo.getMobile());
        if (smsCode == wxAuthRegisterBo.getCode()) {
            return true;
        }
        return false;
    }
}
